package com.chushouya.order.service.common.impl;

import com.general.framework.core.exception.Ex;
import com.general.framework.core.lang.*;
import com.general.framework.web.utils.ExcelUtil;
import com.chushouya.manager.dao.entity.ClerkEntity;
import com.chushouya.manager.dto.admin.clerk.ClerkListDTO;
import com.chushouya.manager.service.api.ClerkApiService;
import com.chushouya.order.dao.entity.StatClerkOrderDayEntity;
import com.chushouya.order.dao.repository.StatClerkOrderDayRepository;
import com.chushouya.order.dto.api.stat.ClerkOrderDayStatQuery;
import com.chushouya.order.dto.api.stat.ClerkOrderMonthDTO;
import com.chushouya.order.dto.api.stat.ClerkOrderMonthExport;
import com.chushouya.order.dto.api.stat.ClerkOrderRangeQuery;
import com.chushouya.order.service.common.ClerkOrderDayStatTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class ClerkOrderDayStatTaskServiceImpl implements ClerkOrderDayStatTaskService {

    /**
     * 忽略统计的业务员
     */
    private static final String IGNORE_STAT_CLERK_LIST = "ignore_stat_clerk_list";

    @Resource
    private ClerkApiService clerkApiService;

    @Resource
    private StatClerkOrderDayRepository clerkOrderDayStatRepository;

    @Resource
    private ClerkOrderDayStatTaskService clerkOrderDayStatTaskService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clerkOrderTodayStat(Long clerkId, Date date) {
        Date statDate;
        List<ClerkListDTO> allClerkList = this.selectAllClerk(clerkId);
        if (Objects.isNull(date)) {
            statDate = Dates.getFirstTime(Dates.getTimeNow());
        } else {
            statDate = Dates.getFirstTime(date);
        }
        this.clerkOrderDayStatHandler(statDate, allClerkList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clerkOrderYesterdayStat(Long clerkId, Date date) {
        Date statDate;
        List<ClerkListDTO> allClerkList = this.selectAllClerk(clerkId);
        if (Objects.isNull(date)) {
            statDate = Dates.getFirstTime(Dates.addDays(Dates.getTimeNow(), -1));
        } else {
            statDate = Dates.getFirstTime(Dates.addDays(date, -1));
        }
        this.clerkOrderDayStatHandler(statDate, allClerkList);
    }

    private void clerkOrderDayStatHandler(Date statDate, List<ClerkListDTO> allClerkList) {
        final Date startTime = Dates.getFirstTime(statDate);
        final Date endTime = Dates.getLastTime(statDate);
        final Date timeNow = Dates.getTimeNow();
        allClerkList.forEach(clerk -> {
            try {
                clerkOrderDayStatTaskService.statOne(statDate, startTime, endTime, timeNow, clerk.getClerkId(), clerk.getClerkName(),clerk.getCity(),clerk.getUserType());
            } catch (Exception e) {
                log.error("统计业务员订单数据异常[{},{}],statDate:{},{}", clerk.getClerkId(), clerk.getClerkName(), statDate, e.getMessage());
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void statOne(Date statDate, Date startTime, Date endTime, Date timeNow, Long clerkId, String clerkName,String city,Integer userType) {
        try {
            ClerkOrderDayStatQuery query = new ClerkOrderDayStatQuery();
            query.setClerkId(clerkId);
            query.setStatDate(statDate);
            StatClerkOrderDayEntity orderDayStat = clerkOrderDayStatRepository.selectOne(query);
            StatClerkOrderDayEntity stat = new StatClerkOrderDayEntity();
            stat.setStatDate(statDate);
            if (Objects.isNull(orderDayStat)) {
                stat.setStatDate(statDate);
                stat.setClerkId(clerkId);
                stat.setClerkName(clerkName);
                stat.setCity(city);
                stat.setUserType(userType);
                stat.setCreateTime(timeNow);
            } else {
                stat.setStatId(orderDayStat.getStatId());
            }
            stat.setLastStatTime(timeNow);
            this.setStatField(startTime, endTime, clerkId, stat);
            if (Objects.isNull(orderDayStat)) {
                clerkOrderDayStatRepository.insertSelective(stat);
            } else {
                clerkOrderDayStatRepository.updateByPrimaryKeySelective(stat);
            }
            log.info("===>统计业务员订单完成,统计对象:[{},{}],statDate:{}", clerkId, clerkName, statDate);
        } catch (Exception e) {
            log.error("统计业务员订单错误,统计对象:[{},{}],statDate:{}", clerkId, clerkName, statDate, e);
        }
    }

    @Override
    public List<ClerkOrderMonthDTO> statClerkOrderMonth(ClerkOrderRangeQuery query) {
        Validate.isNull(query.getStatStartDate(), "统计日期不能为空");
        Validate.isNull(query.getStatEndDate(), "统计日期不能为空");
        final Long clerkId = query.getClerkId();
        return handleClerkOrderMonth(clerkOrderDayStatRepository.statClerkOrderMonth(clerkId,query.getStatStartDate(), query.getStatEndDate()),query);
    }

    @Override
    public List<ClerkOrderMonthDTO> statClerkOrderDay(ClerkOrderRangeQuery query) {
        final Long clerkId = query.getClerkId();
        return handleClerkOrderDay(clerkOrderDayStatRepository.statClerkOrderDay(clerkId,query.getStatStartDate(), query.getStatEndDate()),query);
    }

    @Override
    public ClerkOrderMonthDTO statClerkOrderCount(ClerkOrderRangeQuery query) {
        final Long clerkId = query.getClerkId();
        StatClerkOrderDayEntity clerkOrderCount = clerkOrderDayStatRepository.statClerkOrderCount(clerkId,query.getStatStartDate(), query.getStatEndDate());
        ClerkOrderMonthDTO clerkOrderMonthDTO = Beans.copy(clerkOrderCount, ClerkOrderMonthDTO.class);
        clerkOrderMonthDTO.setStatStartDate(Dates.format(query.getStatStartDate(), Dates.FMT_YYYY_MM_DD));
        clerkOrderMonthDTO.setStatEndDate(Dates.format(query.getStatEndDate(), Dates.FMT_YYYY_MM_DD));
        return clerkOrderMonthDTO;
    }

    @Override
    public void statClerkOrderMonthExport(HttpServletResponse response, ClerkOrderRangeQuery query) {
        try {
            List<ClerkOrderMonthDTO> clerkOrderMonthList = this.statClerkOrderMonth(query);
            List<ClerkOrderMonthExport> clerkOrderMonthExportList = Beans.copyList(clerkOrderMonthList, ClerkOrderMonthExport.class);
            log.info("每月业务员订单统计导出,导出数据量:{}", clerkOrderMonthList.size());
            clerkOrderMonthExportList.forEach(clerkOrderMonthExport -> {
                if (clerkOrderMonthExport.getCompleteCount() == null || clerkOrderMonthExport.getDispatchCount() == 0) {
                    clerkOrderMonthExport.setRate("---");
                }else {
                    clerkOrderMonthExport.setRate(clerkOrderMonthExport.getCompleteCount() * 100 / clerkOrderMonthExport.getDispatchCount() + "%");
                }
            });
            String fileName = Strings.format("每月业务员订单统计导出-{}", Dates.dateTimeNow());
            new ExcelUtil<>(ClerkOrderMonthExport.class).exportExcel(response, clerkOrderMonthExportList, fileName, "每月业务员订单统计导出");
        } catch (Exception e) {
            log.error("每月业务员订单统计导出,{}", e.getMessage());
            throw Ex.systemError("每月业务员订单统计导出");
        }
    }

    @Override
    public List<ClerkOrderMonthDTO> statClerkOrderDayByMonth(ClerkOrderDayStatQuery query) {
        List<StatClerkOrderDayEntity> clerkOrderDayList = clerkOrderDayStatRepository.selectList(query);
        return Beans.copyList(clerkOrderDayList, ClerkOrderMonthDTO.class);
    }

    private void setStatField(Date startTime, Date endTime, Long clerkId, StatClerkOrderDayEntity stat) {
        stat.setDispatchCount(clerkOrderDayStatRepository.selectDispatchCount(clerkId, startTime, endTime));
        stat.setCompleteCount(clerkOrderDayStatRepository.selectCompleteCount(clerkId, startTime, endTime));
        stat.setDeliverCount(clerkOrderDayStatRepository.selectDeliverCount(clerkId, startTime, endTime));
        stat.setStockCount(clerkOrderDayStatRepository.selectStockCount(clerkId, startTime, endTime));
        stat.setReturnedCount(clerkOrderDayStatRepository.selectReturnedCount(clerkId, startTime, endTime));
        stat.setSelfCreateCount(clerkOrderDayStatRepository.selectSelfCreateCount(clerkId, startTime, endTime));
        stat.setCancelCount(clerkOrderDayStatRepository.selectCancelCount(clerkId, startTime, endTime));
        stat.setCloseCount(clerkOrderDayStatRepository.selectCloseCount(clerkId, startTime, endTime));
        stat.setBackoutCount(clerkOrderDayStatRepository.selectBackoutCount(clerkId, startTime, endTime));
        stat.setMultiCount(clerkOrderDayStatRepository.selectMultiCount(clerkId, startTime, endTime));
    }

    private List<ClerkListDTO> selectAllClerk(Long clerkId) {
        if (Longs.notNullAndZero(clerkId)) {
            return Lists.asList(Beans.copy(clerkApiService.getClerkInfo(clerkId), ClerkListDTO.class));
        }
        List<ClerkEntity> clerkList = clerkApiService.getAllClerkList();
        return Beans.copyList(clerkList, ClerkListDTO.class);
    }

    /**
     * 所有业务员订单格式化
     */
    private List<ClerkOrderMonthDTO> handleClerkOrderMonth(List<StatClerkOrderDayEntity> clerkOrderDayList, ClerkOrderRangeQuery query) {
        List<ClerkOrderMonthDTO> clerkOrderMonthList = new ArrayList<>();
        //忽略统计的业务员
//        List<Long> ignoreClerkIdList = query.getIgnoreClerkIdList();
        clerkOrderDayList.forEach(stat -> {
            ClerkOrderMonthDTO clerkOrderMonth = Beans.copy(stat, ClerkOrderMonthDTO.class);
            clerkOrderMonth.setStatStartDate(Dates.format(query.getStatStartDate(), Dates.FMT_YYYY_MM_DD));
            clerkOrderMonth.setStatEndDate(Dates.format(query.getStatEndDate(), Dates.FMT_YYYY_MM_DD));
//            if (!ignoreClerkIdList.contains(stat.getClerkId())) {
//                clerkOrderMonthList.add(clerkOrderMonth);
//            }
        });
        return clerkOrderMonthList;
    }

    /**
     * 某个业务员订单格式化
     */
    private List<ClerkOrderMonthDTO> handleClerkOrderDay(List<StatClerkOrderDayEntity> clerkOrderDayList, ClerkOrderRangeQuery query) {
        List<ClerkOrderMonthDTO> clerkOrderMonthList = new ArrayList<>();
        clerkOrderDayList.forEach(stat -> {
            ClerkOrderMonthDTO clerkOrderMonth = Beans.copy(stat, ClerkOrderMonthDTO.class);
            clerkOrderMonth.setStatStartDate(Dates.format(stat.getStatDate(), Dates.FMT_YYYY_MM_DD));
            clerkOrderMonth.setStatEndDate(Dates.format(stat.getStatDate(), Dates.FMT_YYYY_MM_DD));
            clerkOrderMonthList.add(clerkOrderMonth);
        });
        return clerkOrderMonthList;
    }


}
